package com.cory.module.job.core.handle;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.handler.inter.IExcelDictHandler;
import com.alibaba.fastjson.JSONObject;
import com.cory.boot.component.easypoi.IExcelDictHandlerImpl;
import com.cory.boot.component.uploader.UploaderConfig;
import com.cory.boot.utils.SpringUtils;
import com.cory.module.job.domain.entity.JobExcelExport;
import com.cory.module.job.service.JobExcelExportService;
import com.cory.utils.bean.ReflectioUtils;
import com.cory.utils.file.FileUtils;
import com.cory.utils.lang.DateUtils;
import com.github.pagehelper.PageHelper;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.FileOutputStream;
import java.util.List;
import java.util.Random;

@Slf4j
public abstract class ExcelExportJobHandle<P, T> {

    private JobExcelExportService jobExcelExportService = SpringUtils.getBean(JobExcelExportService.class);

    @Getter
    @Setter
    protected int exportMode = 1;  // 1：当前项目导出，2：任务系统导出
    
    @SuppressWarnings({"rawtypes", "unchecked"})
    public void run(JobExcelExport job) {
        ExportParams exportParams = new ExportParams();
        exportParams.setCreateHeadRows(true);
        exportParams.setDictHandler(this.excelDictHandler());

        int pageSize = 1000;
        final int[] okNum = {0};
        
        try {
            this.doBefore(job);
            
            Class<P> P = ReflectioUtils.getClassGenricType(this.getClass(), 0);
            P param = JSONObject.parseObject(job.getParam(), P);
            
            Class<T> T = ReflectioUtils.getClassGenricType(this.getClass(), 1);
            Workbook workbook = ExcelExportUtil.exportBigExcel(exportParams, T, (queryParams, pageNo) -> {
                if (jobExcelExportService.getById(job.getId()).getState() == 9) {
                    return null;
                }

                PageHelper.startPage(pageNo, pageSize);
                List list = this.list(param);

                if (list.size() > 0) {
                    okNum[0] = okNum[0] + list.size();
                    JobExcelExport update = new JobExcelExport().setId(job.getId()).setOkNum(okNum[0]);
                    jobExcelExportService.updateById(update);
                }
                return list.size() == 0 ? null : list;
            }, param);

            String suffix = job.getFileName().substring(job.getFileName().lastIndexOf(".") + 1);
            String newName = DateUtils.getDate("yyyyMMddHHmmss") + "_" + new Random().nextInt(1000) + "." + suffix;
            String filePath = "/resource/export/" + DateUtils.getYear() + "/" + DateUtils.getMonth();
            String fileId = filePath + "/" + newName;
            FileUtils.createDirectory(UploaderConfig.resource + filePath);
            workbook.write(new FileOutputStream(UploaderConfig.resource + fileId));

            JobExcelExport update = new JobExcelExport().setId(job.getId()).setState(1).setFileId(fileId);
            jobExcelExportService.updateById(update);
            
            this.doAfter(job);
        } catch (Exception e) {
            log.error("", e);
            JobExcelExport update = new JobExcelExport().setId(job.getId()).setState(2);
            jobExcelExportService.updateById(update);
        }
    }

    protected IExcelDictHandler excelDictHandler() {
        return new IExcelDictHandlerImpl();
    }
    
    public void doBefore(JobExcelExport job) {}
    
    public void doAfter(JobExcelExport job) {}

    public abstract List<T> list(P param);

    public abstract Integer totalNum(P param);
}
